/**
 *
 */
package com.bsoft.gol.hcb.service.evaluation;

import com.bsoft.gol.hcb.dao.evaluation.*;
import com.bsoft.gol.hcb.utils.DateUtils;
import ctd.account.UserRoleToken;
import ctd.account.user.User;
import ctd.controller.exception.ControllerException;
import ctd.net.rpc.Client;
import ctd.spring.boot.annotation.SsdevService;
import ctd.util.annotation.RpcService;
import hcn.base.Organization;
import hcn.bean.UserVo;
import hcn.enums.EvaluationBusinessTypeEnum;
import hcn.enums.ReviewEvaluationFlagEnum;
import hcn.util.CommonUtils;
import hcn.util.RpcUserToken;
import org.apache.commons.lang3.StringUtils;
import org.atag.util.bbp.UserUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import pcn.bean.consultation.BaseEvaluationRecordList;
import pcn.bean.consultation.EvaluationLabelBean;
import pcn.bean.consultation.PatientEvaluateDetailQo;
import pcn.bean.sign.EvaluateRecordDto;
import pcn.bean.sign.EvaluationRecordQo;
import pcn.consultation.BaseEvaluationLabelrecord;
import pcn.service.BaseEvaluationRecordService;
import pcn.sign.BaseEvaluationDefine;
import pcn.sign.BaseEvaluationItemrecord;
import pcn.sign.BaseEvaluationRecord;
import pcn.sign.DoctInfo;
import pcn.vo.consultation.BaseEvaluationLabelrecordVo;
import pcn.vo.consultation.PatientEvaluateDetailVo;
import pcn.vo.sign.*;
import service.rpc.BaseUserManageUnitIntf;
import service.rpc.DoctorInfoServiceIntf;
import service.rpc.OrganizationInfoIntf;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @since 2017-05-03 04:17:29
 */
@SsdevService("baseEvaluationRecordService")
public class BaseEvaluationRecordServiceImpl implements BaseEvaluationRecordService {

    private final static Logger log = LoggerFactory.getLogger(BaseEvaluationRecordServiceImpl.class);

    @Autowired
    private BaseEvaluationRecordDAO baseEvaluationRecordDAO;
    @Autowired
    private BaseEvaluationItemrecordDAO baseEvaluationItemrecordDAO;
    @Autowired
    private BaseEvaluationLabelrecordDAO baseEvaluationLabelrecordDAO;
    @Autowired
    private DoctorInfoServiceIntf doctorInfoServiceIntf;
    @Autowired
    private BaseUserManageUnitIntf baseUserManageUnitIntf;
    @Autowired
    private OrganizationInfoIntf organizationInfoService;
    @Autowired
    private BaseEvaluationLabelDAO baseEvaluationLabelDAO;
    @Autowired
    private BaseEvaluationDefineDAO baseEvaluationDefineDAO;

    @RpcService
    @Override
    public Integer saveEvaluation(EvaluateRecordDto dto) throws Exception {
        if (CommonUtils.isEmpty(dto.getEvaluationRecord())) {
            throw new ControllerException("评价内容不能为空");
        }
        if (CommonUtils.isEmpty(dto.getEvaluationRecord().getBusinessType())) {
            throw new ControllerException("业务类型不能为空");
        }

        //评价保存
        BaseEvaluationRecord record = dto.getEvaluationRecord();
        //若为家医服务评价类型则先判断是否为家医融合，是保存到公卫，否则保存本地。
        if ("2".equals(record.getBusinessType())) {
            try {
                //为空时，则为家医融合业务。保存到公卫
                Client.rpcInvoke("pcn.pcnSignPackService", "saveResidentEvaluation", dto);
//                return Constants.ONE;
            } catch (Throwable throwable) {
                log.error("保存公卫评价rpc调用异常:", throwable.getMessage());
                throw new ControllerException("保存公卫评价异常：" + throwable.getMessage());
            }
        }

        //保存本地
        record.setAddTime(new Date());
        UserRoleToken current = UserRoleToken.getCurrent();
        String userId = current.getUserId();
        record.setUserId(userId);
        User userByUid = UserUtils.getUserByUid(userId);
        record.setPhoneNo(userByUid.getMobile());
        // 默认评价人为当前登录用户，如果前端提交则使用前端传入姓名作为评价人
        if (StringUtils.isEmpty(dto.getPersonName())) {
            record.setPersonName(current.getUserName());
        } else {
            record.setPersonName(dto.getPersonName());
        }

        Organization organization = organizationInfoService.getOrgDetailByOrgId(record.getOrgId());
        if (organization != null) {
            record.setOrgName(organization.getFullName());
        }
        record.setVerifyState("0");//0待审核 1审核通过 2
        baseEvaluationRecordDAO.save(record);
        //保存评价项目记录
        int id = record.getId();
        List<BaseEvaluationItemrecord> list = dto.getItemList();
        if (CommonUtils.isNotEmpty(list)) {
            for (BaseEvaluationItemrecord baseEvaluationItemrecord : list) {
                baseEvaluationItemrecord.setEvaluateDt(new Date());
                baseEvaluationItemrecord.setRecordId(id);
                baseEvaluationItemrecordDAO.save(baseEvaluationItemrecord);
            }
        }
        //保存医生标签记录表
        List<EvaluationLabelBean> labelList = dto.getLabelList();
        if (CommonUtils.isNotEmpty(labelList)) {
            if (labelList.size() > 0) {
                for (EvaluationLabelBean evaluationLabelBean : labelList) {
                    BaseEvaluationLabelrecord baseEvaluationLabelrecord = new BaseEvaluationLabelrecord();
                    baseEvaluationLabelrecord.setContent(evaluationLabelBean.getContent());
                    baseEvaluationLabelrecord.setEvaluateDt(new Date());
                    baseEvaluationLabelrecord.setLabelId(evaluationLabelBean.getId());
                    baseEvaluationLabelrecord.setRecordId(id);
                    baseEvaluationLabelrecordDAO.save(baseEvaluationLabelrecord);
                }
            }
        }

        //追评标志 -1 不启用追评  0 未追评  1 已追评
        int reviewEvaluationFlag = ReviewEvaluationFlagEnum.UNREVIEW.getTypeCode();

        BaseEvaluationDefine define = baseEvaluationDefineDAO.getBaseEvaluationDefineByBussinessTypeAndStatus(record.getBusinessType(), (byte) 1);
        if (null != define) {
            //不启用追评
            if ("0".equals(define.getAddEvaluationFlag())) {
                reviewEvaluationFlag = ReviewEvaluationFlagEnum.UNOPEN.getTypeCode();
            }
        }

        //家医签约服务
        if (EvaluationBusinessTypeEnum.SIGN.getTypeCode().equals(record.getBusinessType())) {
            try {
                //修改服务记录评价状态
                Client.rpcInvoke("pcn.pcnServiceExecDaoService", "updateEvaluateFalg", dto.getAccasion() != null ? dto.getAccasion() : "1");
            } catch (Throwable throwable) {
                log.error("修改服务记录评价状态rpc调用异常:", throwable.getMessage());
            }
            //3：在线咨询 18：复诊配药评价
        } else if (EvaluationBusinessTypeEnum.CONSULT.getTypeCode().equals(record.getBusinessType())
                || EvaluationBusinessTypeEnum.RETURNVISIT.getTypeCode().equals(record.getBusinessType())) {
            try {
                Client.rpcInvoke("hco.consult", "updateEvaluationFlag", record.getBusinessId(), id);
            } catch (Throwable throwable) {
                log.error("修改互联网诊疗评价状态rpc调用异常:", throwable.getMessage());
            }
        } else if (EvaluationBusinessTypeEnum.REG.getTypeCode().equals(record.getBusinessType())) {
            try {
                //本次评价是追评
                if ("2".equals(dto.getAccasion())) {
                    reviewEvaluationFlag = ReviewEvaluationFlagEnum.REVIEW.getTypeCode();
                }

                Client.rpcInvoke("hcr.odsRegprepareService", "updateEvaluationFlag", record.getBusinessId(), id, reviewEvaluationFlag);
            } catch (Throwable throwable) {
                log.error("修改预约挂号评价状态rpc调用异常:", throwable.getMessage());
            }
        } else if (EvaluationBusinessTypeEnum.RECOVERY.getTypeCode().equals(record.getBusinessType())) {
            try {
                Client.rpcInvoke("recovery.thirdTreatmentRecord", "updateEvaluationStatus", record.getBusinessId(), String.valueOf(id));
            } catch (Throwable throwable) {
                log.error("修改康复评价状态rpc调用异常:", throwable);
            }
        }
        return id;
    }

    /**
     * 用户评价记录
     *
     * @param qo
     * @return
     */
    @RpcService
    @Override
    public List<BaseEvaluationRecord> queryEvaluationRecord(EvaluationRecordQo qo) {
        qo.setUserId(RpcUserToken.getUserId());

        List<BaseEvaluationDefine> baseEvaluationDefines = baseEvaluationDefineDAO.queryBaseEvaluationDefineByPriorLevel((byte) 1);
        if (CommonUtils.isNotEmpty(baseEvaluationDefines)) {
            List<Integer> collect = baseEvaluationDefines.stream().map(BaseEvaluationDefine::getId).collect(Collectors.toList());
            qo.setDefineIdList(collect);
        }
        //查询本地评价
        List<BaseEvaluationRecord> baseEvaluationRecordList = baseEvaluationRecordDAO.queryEvaluationRecordList(qo);

        Collections.sort(baseEvaluationRecordList, new Comparator<BaseEvaluationRecord>() {
            @Override
            public int compare(BaseEvaluationRecord o1, BaseEvaluationRecord o2) {
                Long date1 = DateUtils.toDate(o1.getAddTime()).getTime();
                Long date2 = DateUtils.toDate(o2.getAddTime()).getTime();
                return date1.compareTo(date2);
            }
        });
        return baseEvaluationRecordList;
    }

    /*
     * @description 查询公卫的居民[评价接口
     * @exception
     * @author      zangsf
     * @date        2021/9/16 9:20
     **/
    @RpcService
    public List<BaseEvaluationRecord> queryEvaluationRecordChis(EvaluationRecordQo qo) {
        qo.setUserId(RpcUserToken.getUserId());
        qo.setBusinessType(EvaluationBusinessTypeEnum.SIGN.getTypeCode());
        //公卫那边没有居民评价的入口，我们查看评价直接从本地获取就好了
        List<BaseEvaluationRecord> baseEvaluationRecords = queryEvaluationRecord(qo);
        return baseEvaluationRecords;
//        //查询公卫家医评价
//        try {
//            List<BaseEvaluationRecord> evaluationRecords = (List<BaseEvaluationRecord>) Client.rpcInvoke("pcn.pcnSignPackService", "queryChisEvaluationRecord", qo.getUserId());
//            if (CommonUtils.isEmpty(evaluationRecords)) {
//                return baseEvaluationRecordList;
//            }
//            baseEvaluationRecordList.addAll(evaluationRecords);
//        } catch (Throwable throwable) {
//            log.error("查询公卫评价记录异常:", throwable.getMessage());
//        }
//
//        Collections.sort(baseEvaluationRecordList, new Comparator<BaseEvaluationRecord>() {
//            @Override
//            public int compare(BaseEvaluationRecord o1, BaseEvaluationRecord o2) {
//                Long date1 = DateUtils.toDate(o1.getAddTime()).getTime();
//                Long date2 = DateUtils.toDate(o2.getAddTime()).getTime();
//                return date2.compareTo(date1);
//            }
//        });
//        return baseEvaluationRecordList;
    }

    /**
     * @description: 更新评价
     * @author: chenJij@bsoft.com.cn
     * @date: 2021/6/4 19:17
     * @param: null
     * @return:
     */
    @RpcService
    @Override
    public void updateEvaluation(BaseEvaluationRecord baseEvaluationRecord) throws ControllerException {
        if (CommonUtils.isEmpty(baseEvaluationRecord)) {
            baseEvaluationRecordDAO.update(baseEvaluationRecord);
        }
    }

    /**
     * 获取在线咨询评价列表
     *
     * @param evaluationRecordQo
     * @return
     */
    @Override
    @RpcService
    public Map<String, Object> queryConsultEvaluationList(pcn.bean.consultation.EvaluationRecordQo evaluationRecordQo) throws ControllerException {
        try {
            Map<String, Object> map = new HashMap<>();

            List<BaseEvaluationRecordList> recordListList = baseEvaluationRecordDAO.queryEvaluationRecordLists(evaluationRecordQo);
            Long recordCount = baseEvaluationRecordDAO.getEvaluationRecordCount(evaluationRecordQo);
            map.put("list", recordListList);
            map.put("total", recordCount);
            return map;
        } catch (Throwable e) {
            e.printStackTrace();
            throw new ControllerException("获取评价列表失败");
        }
    }

    /**
     * 获取评价配置
     *
     * @param businessType
     * @return
     * @throws ControllerException
     */
    @Override
    @RpcService
    public Map<String, Object> findBaseEvaluationDefineAndItem(String businessType) throws ControllerException {
        return null;
    }

    /**
     * @Describe: 审核在线咨询评价
     * @Param: [baseEvaluationRecord]
     * @Return: void
     * @Author: zhengcb10708
     * @Date: 2021/5/31 17:22
     */
    @RpcService
    @Override
    public void reditConsultEvaluation(BaseEvaluationRecord baseEvaluationRecord) throws ControllerException {
        if (CommonUtils.isEmpty(baseEvaluationRecord)) {
            throw new ControllerException("必要入参不能为空");
        }
        baseEvaluationRecordDAO.update(baseEvaluationRecord);
        //更新评分
        if ("1".equals(baseEvaluationRecord.getVerifyState())) {
            Double levelAvg = baseEvaluationItemrecordDAO.getLevelAvg(baseEvaluationRecord.getId());
            DoctInfo doctInfo = doctorInfoServiceIntf.getDocInfo(baseEvaluationRecord.getObjectId());
            if (null != doctInfo && null != levelAvg) {
                doctInfo.setAverageScore(levelAvg);
                doctorInfoServiceIntf.updateDocInfo(doctInfo);
            }
        }
    }

    /**
     * @Describe: 查询评价记录
     * @Param: [recordId]
     * @Return: pcn.sign.BaseEvaluationRecord
     * @Author: zhengcb10708
     * @Date: 2021/5/31 17:07
     */
    @RpcService
    @Override
    public BaseEvaluationRecord queryBaseEvaluationRecord(int recordId) throws ControllerException {
        return baseEvaluationRecordDAO.get(recordId);
    }

    /**
     * 居民端-获取医生评价标签
     *
     * @param objectId
     * @return List<BaseEvaluationLabelrecord>
     */
    @RpcService
    @Override
    public List<BaseEvaluationLabelrecordVo> queryDoctorEvaluateLabelList(String objectId) {
        List<BaseEvaluationLabelrecordVo> list = baseEvaluationLabelrecordDAO.queryDoctorEvaluateLabelList(objectId, null);
        if (CommonUtils.isNotEmpty(list)) {
            //去重
            list = list.stream().collect(
                    Collectors.collectingAndThen(Collectors.toCollection(
                                    () -> new TreeSet<>(Comparator.comparing(BaseEvaluationLabelrecordVo::getContent))),
                            ArrayList::new));
        }

        if (CommonUtils.isNotEmpty(list)) {
            for (BaseEvaluationLabelrecordVo baseEvaluationLabelrecordVo : list) {
                baseEvaluationLabelrecordVo.setCount(baseEvaluationLabelrecordDAO.countDoctorEvaluateLabel(objectId,
                        baseEvaluationLabelrecordVo.getContent(), null));
            }
        }
        return list;
    }

    /**
     * 居民端-获取问诊居民对医生的评价列表
     *
     * @param qo
     * @return List<BaseEvaluationLabelrecord>
     */
    @RpcService
    @Override
    public List<PatientEvaluateDetailVo> queryPatientEvaluateList(PatientEvaluateDetailQo qo) {
        Map<String, Object> map = new HashMap<>();
        List<PatientEvaluateDetailVo> list = baseEvaluationLabelrecordDAO.queryPatientEvaluateList(qo);
        Long count = baseEvaluationRecordDAO.getPatientEvaluateCount(qo.getDoctorId());
        map.put("list", list);
        map.put("total", count);
        if (list != null && list.size() > 0) {
            for (PatientEvaluateDetailVo bean : list) {
                bean.setScore(String.valueOf(baseEvaluationItemrecordDAO.getLevelAvg(bean.getId())));
                bean.setLabelList(baseEvaluationLabelrecordDAO.queryBaseEvaluationLabelrecordList(bean.getId()));
            }
        }
        return list;
    }

    /**
     * @Describe: 删除评价标签
     * @Param: [id]
     * @Return: void
     * @Author: zhengcb10708
     * @Date: 2021/5/28 17:09
     */
    @RpcService
    @Override
    public void deleteLabel(int id) throws Exception {
        baseEvaluationLabelDAO.remove(id);
    }

    @RpcService
    @Override
    public EvaluationRecordDetailVo queryEvaluationRecordDetail(int id) throws Exception {
        //获取公卫评价记录详情，若有则说明评价是公卫融合，否则再查询本地。
//        try {
//            EvaluationRecordDetailVo recordDetailVo = (EvaluationRecordDetailVo) Client.rpcInvoke("pcn.pcnSignPackService", "queryChisEvaluationRecordDetail", new Integer(id));
//            if (recordDetailVo != null) {
//                return recordDetailVo;
//            }
//        } catch (Throwable throwable) {
//            log.error("查询公卫评价详情异常:", throwable.getMessage());
//        }

        //获取评价记录
        EvaluationRecordDetailVo vo = new EvaluationRecordDetailVo();
        BaseEvaluationRecord baseEvaluationRecord = baseEvaluationRecordDAO.getBaseEvaluationRecordById(id);
        if (null != baseEvaluationRecord) {
            //获取用户名
            UserVo userVo = baseUserManageUnitIntf.getUserById(RpcUserToken.getUserId());
            vo.setUserName(userVo.getUserName() == null ? "" : userVo.getUserName());
            vo.setAddTime(baseEvaluationRecord.getAddTime());
            vo.setContent(baseEvaluationRecord.getContent());
            vo.setId(String.valueOf(baseEvaluationRecord.getId()));
            //获取评价项和分数列表
            List<BaseEvaluationItemRecordVo> list = baseEvaluationItemrecordDAO.getBaseEvaluationItemrecordByRecordId(id);
            if (list != null && list.size() > 0) {
                int level = 0;
                for (BaseEvaluationItemRecordVo item : list) {
                    item.setLevel(item.getLevels());
                    level += item.getLevel();
                }
                vo.setAverageLevel(new BigDecimal(level).divide(new BigDecimal(list.size()), BigDecimal.ROUND_CEILING).doubleValue());
            }
            vo.setItemList(list);
            List<EvaluationLabelBean> labelList = baseEvaluationLabelrecordDAO.queryBaseEvaluationLabelRecord(id);
            vo.setLabelList(labelList);

            //获取追评记录
            BaseEvaluationDefine define = baseEvaluationDefineDAO.getBaseEvaluationDefineByBussinessTypeAndStatus(baseEvaluationRecord.getBusinessType(), (byte) 2);
            if (null != define) {
                BaseEvaluationRecord evaluationRecord = baseEvaluationRecordDAO.getByDefineIdAndBusinessId(define.getId(), baseEvaluationRecord.getBusinessType(), baseEvaluationRecord.getBusinessId());
                if (null != evaluationRecord) {
                    vo.setReviewTime(evaluationRecord.getAddTime());
                    vo.setReviewContent(evaluationRecord.getContent());
                    //获取评价项和分数列表
                    List<BaseEvaluationItemRecordVo> reviewList = baseEvaluationItemrecordDAO.getBaseEvaluationItemrecordByRecordId(evaluationRecord.getId());
                    if (reviewList != null && reviewList.size() > 0) {
                        for (BaseEvaluationItemRecordVo item : reviewList) {
                            item.setLevel(item.getLevels());
                        }
                    }
                    vo.setReviewItemList(reviewList);
                    List<EvaluationLabelBean> reviewLabelList = baseEvaluationLabelrecordDAO.queryBaseEvaluationLabelRecord(evaluationRecord.getId());
                    vo.setReviewLabelList(reviewLabelList);
                }
            }
        }

        return vo;
    }

    /**
     * 根据服务记录id查询评价详情
     *
     * @param qo
     */
    @Override
    public ExeEvaluationRecordDetailVo queryEvaluationRecordByExe(EvaluationRecordQo qo) {
        return null;
    }

    /**
     * 评价列表
     *
     * @param qo
     * @return
     */
    @Override
    public BaseEvaluationRecordAppVo findEvaluationRecordListAll(EvaluationRecordQo qo) {
        return null;
    }

    /**
     * 评价详情
     *
     * @param qo
     * @return
     */
    @Override
    public BaseEvaluationRecordForWebVo getDetail(EvaluationRecordQo qo) {
        return null;
    }

    /**
     * 居民端-获取医生评价标签
     *
     * @param evaluateIdList
     * @return List<BaseEvaluationLabelrecord>
     */
    @RpcService
    public List<BaseEvaluationLabelrecordVo> queryEvaluateLabelByRecordId(List<String> evaluateIdList) {
        List<BaseEvaluationLabelrecordVo> list = baseEvaluationLabelrecordDAO.queryDoctorEvaluateLabelList(null, evaluateIdList);
        if (CommonUtils.isNotEmpty(list)) {
            //去重
            list = list.stream().collect(
                    Collectors.collectingAndThen(Collectors.toCollection(
                                    () -> new TreeSet<>(Comparator.comparing(BaseEvaluationLabelrecordVo::getContent))),
                            ArrayList::new));
        }

        if (CommonUtils.isNotEmpty(list)) {
            for (BaseEvaluationLabelrecordVo baseEvaluationLabelrecordVo : list) {
                baseEvaluationLabelrecordVo.setCount(baseEvaluationLabelrecordDAO.countDoctorEvaluateLabel(null,
                        baseEvaluationLabelrecordVo.getContent(), evaluateIdList));
            }
        }
        return list;
    }
}